'use strict';

var utils = require('./utils');
var bind = require('./helpers/bind');
var Axios = require('./core/Axios');
var mergeConfig = require('./core/mergeConfig');
var defaults = require('./defaults');

/**
 * Create an instance of Axios
 *
 * @param {Object} defaultConfig The default config for the instance
 * @return {Axios} A new instance of Axios
 */
function createInstance(defaultConfig) {
	// 创建一个 axios 实例
  var context = new Axios(defaultConfig);
  // 将 instance 指向 Axios.prototype.request 方法，且上下文绑定 context（axios实例）
  // 调用 instance 实际上是调用 Axios.prototype.request 方法
  var instance = bind(Axios.prototype.request, context);

  // 将 Axios.prototype 对象上的自身属性和方法扩展到 instance 上，即 get、post、put 等方法
  // 并且改变函数的指向 context，调用原型链上的方法时，this 就会绑定为 context
  // Copy axios.prototype to instance
  utils.extend(instance, Axios.prototype, context);

  // 把 context 自身的属性和方法拷贝到 instance 上
  // extend 内部 使用的 forEach 遍历方法，采用是 in 判断，只会拷贝自身属性，不会拷贝原型链上的
  // instance 就有了 defaults（默认配置）、interceptors（拦截器） 等属性
  // Copy context to instance
  utils.extend(instance, context);

  return instance;
}

// createInstance 方法期望是得到一个 函数，该函数指向了  Axios.prototype.request
// 这个函数还有 Axios.prototype 上的每个方法作为静态方法，并且这些方法都指定上下文为 同一个对象
// Create the default instance to be exported
var axios = createInstance(defaults);

// Expose Axios class to allow class inheritance
axios.Axios = Axios;

// 预留创建新的实例的方法
// Factory for creating new instances
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};

// Expose Cancel & CancelToken
axios.Cancel = require('./cancel/Cancel');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');

// Expose all/spread
axios.all = function all(promises) {
  return Promise.all(promises);
};
axios.spread = require('./helpers/spread');

// Expose isAxiosError
axios.isAxiosError = require('./helpers/isAxiosError');

module.exports = axios;

// Allow use of default import syntax in TypeScript
module.exports.default = axios;
